﻿using AMEC.PCSoftware.CommunicationProtocol.CrazyHein.FINS.Message;
using System.Runtime.InteropServices;

namespace AMEC.PCSoftware.CommunicationProtocol.CrazyHein.FINS.Command
{ 
    public class Handshake
    {
        public static int BUILD_REQUEST(byte clientNodeAddress, ref MESSAGE_T message)
        {
            message.length = 12;
            message.type = Message.Message.HANDSHAKE_RSQ;
            message.error_code = 0;
            MemoryMarshal.Write(message.data, Message.Message.SWAP32(clientNodeAddress));
            return Marshal.SizeOf<MESSAGE_HEADER_T>() + 4;
        }

        public static int BUILD_REQUEST(byte clientNodeAddress, byte[] message)
        {
            MESSAGE_HEADER_T header = new MESSAGE_HEADER_T();
            header.type = Message.Message.HANDSHAKE_RSQ;
            header.length = Message.Message.SWAP32((uint)(12));
            header.error_code = 0;

            MemoryMarshal.Write(message, header);
            MemoryMarshal.Write<uint>(message.AsSpan(Marshal.SizeOf<MESSAGE_HEADER_T>()), Message.Message.SWAP32((uint)(clientNodeAddress)));

            return Marshal.SizeOf<MESSAGE_HEADER_T>() + 4;
        }

        public static void PARSE_RESPONSE(ReadOnlyMemory<byte> message, out byte clientNodeAddress, out byte serverNodeAddress)
        {
            MESSAGE_HEADER_T header = new MESSAGE_HEADER_T();
            var data = Message.Message.PARSE_RESPONSE(message, out header);
            if (header.type != Message.Message.HANDSHAKE_RES)
                throw new FINSException(FINS_EXCEPTION_CODE_T.RECEIVED_INCORRECT_HANDSHAKE_RESPONSE);

            if(data.Length != 8)
                throw new FINSException(FINS_EXCEPTION_CODE_T.RECEIVED_CORRUPT_HANDSHAKE_RESPONSE);

            clientNodeAddress = (byte)Message.Message.SWAP32(MemoryMarshal.Read<uint>(data.Span));
            serverNodeAddress = (byte)Message.Message.SWAP32(MemoryMarshal.Read<uint>(data.Slice(4).Span));
        }
    }
}
